<?php

/**
 * This is the model class for table "{{user}}".
 *
 * The followings are the available columns in table '{{user}}':
 * @property integer $id
 * @property integer $account_id
 * @property string $first_name
 * @property string $last_name
 * @property string $dob
 * @property string $gender_code
 * @property integer $marital_status_code
 * @property integer $ethnic_code
 * @property string $country_code
 * @property string $contact_number
 * @property string $fax_number
 * @property string $mobile_number
 * @property string $email
 * @property integer $user_role
 * @property string $language_code
 * @property string $username
 * @property string $password
 * @property string $settings
 * @property string $social_provider
 * @property string $social_identifier
 * @property string $social_avatar_url
 * @property string $social_profile_url
 * @property integer $total_points
 * @property integer $total_view
 * @property integer $status_code
 * @property string $verification_code
 * @property string $last_login_time
 * @property string $source
 * @property string $source_info
 * @property string $create_timezone
 * @property string $create_timestamp
 * @property string $create_datetime
 * @property string $create_date
 * @property string $create_time
 * @property integer $create_by
 * @property string $update_timezone
 * @property string $update_timestamp
 * @property string $update_datetime
 * @property string $update_date
 * @property string $update_time
 * @property integer $update_by
 */
class User extends AccountRecord {

    public $name_;
    public $firstName_;
    public $lastName_;

    public $gender_;
    public $dob_;
    public $ethnic_;
    public $religion_;
    public $maritalStatus_;
    
    public $country_;
    public $phoneNumber_;
    public $faxNumber_;
    public $mobileNumber_;
    public $email_;
    public $url_;
    
    public $accountId_;
    public $userRole_;
    public $language_;
    public $username_;
    public $oldPassword_;
    public $password_;
    public $password2_;
    public $temporaryPassword;
    
    public $socialLogin_;
    public $socialPost_;    
    public $socialProvider_;
    public $socialIdentifier_;
    public $socialAvatarUrl_;
    public $socialProfileUrl_;
    
    public $source_;
    public $sourceInfo_;
    public $rememberMe_ = false;
    public $activationKey_;
    public $status_;
    
    /**
     * Returns the static model of the specified AR class.
     * @param string $className active record class name.
     * @return User the static model class
     */
    public static function model($className = __CLASS__) {
        return parent::model($className);
    }

    /**
     * @return string the associated database table name
     */
    public function tableName() {
        return '{{user}}';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules() {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            array('name_, firstName_, lastName_, username_, phoneNumber_, faxNumber_, mobileNumber_, email_, password_, password2_', 'filter', 'filter' => 'trim'),
            //array('name_, firstName_, lastName_, username_','filter','filter'=>array($obj=new CHtmlPurifier(),'purify')),
            
            // profile
            array('firstName_, mobileNumber_', 'required', 'on' => 'adminRegister, adminUpdate, userRegister, userUpdate'),
            array('firstName_, lastName_', 'length', 'max' => 100),
            array('name_, firstName_, lastName_', 'ext.validators.AlphaNumericValidator', 'on' => 'adminRegister, adminUpdate, userRegister, userUpdate'),
            
            array('gender_', 'in', 'range'=>array_keys($this->genderOption), 'allowEmpty'=>false, 'except'=>'login, recovery, userUpdatePassword, setNewPassword'),
            array('dob_', 'date', 'format' => Yii::app()->params['dateFormatRule']),
            array('ethnic_, religion_, maritalStatus_', 'numerical', 'integerOnly'=>true, 'min'=>1, 'max'=>999),
            array('ethnic_', 'in', 'range'=>array_keys($this->ethnicOption)),
            array('religion_', 'in', 'range'=>array_keys($this->religionOption)),
            array('maritalStatus_', 'in', 'range'=>array_keys($this->maritalStatusOption)),
            array('language_', 'in', 'range' => array_keys($this->languageOption), 'allowEmpty' => false, 'on' => 'userRegister, userUpdate'),
            
            // username
            array('username_', 'length', 'max'=>20, 'min'=>2),
            array('username_', 'ext.validators.UsernameValidator', 'on' => 'adminRegister, adminUpdate, userRegister, userUpdate'),
            array('username_', 'unique', 'className'=>get_class($this), 'attributeName'=>'username', 'criteria'=>array('scopes'=>'accessible'), 'on' => 'adminRegister, adminUpdate, userRegister, userUpdate'),
            
            // social login
            array('socialProvider_, socialIdentifier_', 'required', 'on'=>'socialRegister, socialUpdate'),
            array('socialAvatarUrl_, socialProfileUrl_', 'url', 'defaultScheme'=>'http', 'allowEmpty'=>false, 'on'=>'socialRegister, socialUpdate'),
            
            // contact
            array('phoneNumber_, faxNumber_, mobileNumber_', 'length', 'max' => 15),
            array('phoneNumber_, faxNumber_, mobileNumber_', 'ext.validators.ContactNumberValidator'),
            
            // email
            array('email_', 'required', 'except'=>'login, userUpdatePassword, setNewPassword'),
            array('email_', 'length', 'max' => 50),
            array('email_', 'email', 'checkMX' => false),
            array('email_', 'unique', 'className' => get_class($this), 'attributeName' => 'email', 'criteria'=>array('scopes'=>'accessible'), 'except' => 'recovery'),
            
            //array('url_', 'url', 'defaultScheme'=>'http'),
            
            // avatar
            array('image_', 'file', 'types' => 'jpg,gif,png', 'allowEmpty' => true, 'maxSize' => Yii::app()->params['maxAvatarSize'], 'on' => 'adminRegister, adminUpdate, userRegister, userUpdate'),            
            
            // safe list
            array('id_, name_, firstName_, lastName_, username_, image_, gender_, dob_, ethnic_, religion_, maritalStatus_, phoneNumber_, faxNumber_, mobileNumber_, email_, accountId_, userRole_, language_, status_', 'safe', 'on' => 'userRegister, userUpdate, adminSearch, adminRegister, adminUpdate'),

            // login
            array('rememberMe_', 'boolean'),
            array('username_, password_', 'required', 'on' => 'login'),
            array('username_, password_, rememberMe_', 'safe', 'on' => 'login'),
            
            // password
            array('password_, password2_', 'required', 'on' => 'userRegister, userUpdatePassword, setNewPassword'),
            //array('oldPassword_', 'required', 'on' => 'userUpdatePassword'),
            array('oldPassword_, password_, password2_', 'safe', 'on' => 'userUpdatePassword'),
            array('oldPassword_', 'validateOldPassword', 'on' => 'userUpdatePassword'),
            array('password_', 'ext.validators.PasswordStrengthValidator', 'on' => 'userRegister, userUpdatePassword, setNewPassword'),
            array('password_', 'compare', 'compareAttribute' => 'password2_', 'on' => 'userRegister, userUpdatePassword, setNewPassword'),
            
            // control
            array('userRole_', 'in', 'range'=>array_keys($this->userRoleOption), 'allowEmpty'=>false, 'except'=>'login, recovery, userUpdatePassword, setNewPassword'),
            array('status_', 'in', 'range'=>array_keys($this->statusOption), 'allowEmpty'=>false, 'except'=>'login, recovery, userUpdatePassword, setNewPassword'),
            
            array('captcha_', 'required', 'on' => 'userRegister, recovery', 'except' => 'adminRegister, adminUpdate'),
            array('captcha_', 'ext.widgets.captchaExtended.CaptchaExtendedValidator', 'allowEmpty' => !CCaptcha::checkRequirements(), 'on' => 'userRegister, recovery', 'except' => 'adminRegister, adminUpdate'),
            array('captcha_', 'safe', 'on' => 'userRegister, recovery', 'except' => 'adminRegister, adminUpdate'),
            
            array('var_', 'ext.validators.BotDetectionValidator'),
            array('var_', 'safe'),
        );
    }

    /**
     * @return array relational rules.
     */
    public function relations() {
        // NOTE: you may need to adjust the relation name and the related
        // class name for the relations automatically generated below.
        return array(
            // must include
            'creator' => array(self::BELONGS_TO, __CLASS__, 'create_by'),
            'editor' => array(self::BELONGS_TO, __CLASS__, 'update_by'),
            
            // custom
            'account'=> array(self::BELONGS_TO, 'Account', 'account_id', 'scopes'=>array('accessible')),
            'photo' => array(self::HAS_ONE, 'Gallery', 'module_id', 'scopes' => array('module' => __CLASS__, 'primary', 'accessible')),
            'address' => array(self::HAS_ONE, 'Address', 'module_id', 'scopes' => array('module' => __CLASS__, 'primary', 'accessible')),
            'shortListedItem'=>array(self::HAS_ONE, 'ShortList', 'create_by', 'scopes'=>array('module' => 'item', 'accessible')),
        );
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels() {
        return array(
            'id_' => Lang::t('user.profile.lbl.id'),
            'image_'=>Lang::t('user.profile.lbl.avatar'),
            'name_' => Lang::t('user.profile.lbl.name'),
            'firstName_' => Lang::t('user.profile.lbl.first.name'),
            'lastName_' => Lang::t('user.profile.lbl.last.name'),
            'gender_' => Lang::t('user.profile.lbl.gender'),
            'dob_' => Lang::t('user.profile.lbl.dob'),
            'ethnic_' => Lang::t('user.profile.lbl.ethnic'),
            'religion_'=>Lang::t('user.profile.lbl.religion'),
            'maritalStatus_' => Lang::t('user.profile.lbl.marital.status'),
                        
            'phoneNumber_' => Lang::t('user.profile.lbl.phone.number'),
            'faxNumber_' => Lang::t('user.profile.lbl.fax.number'),
            'mobileNumber_' => Lang::t('user.profile.lbl.mobile.number'),
            'email_' => Lang::t('user.profile.lbl.email'),
            //'url_' => Lang::t('user.profile.lbl.url'),
            'accountId_'=>Lang::t('user.profile.lbl.account'),
            'userRole_' => Lang::t('user.profile.lbl.user.role'),
            'language_' => Lang::t('user.profile.lbl.language'),
            'username_' => $this->scenario=='login'? Lang::t('user.profile.lbl.username'): Lang::t('user.profile.lbl.display.name'),
            'oldPassword_' => Lang::t('user.profile.lbl.old.password'),
            'password_' => Lang::t('user.profile.lbl.password'),
            'password2_' => Lang::t('user.profile.lbl.password2'),
            'captcha_' => Lang::t('captcha.lbl'),
            'status_'=>Lang::t('user.profile.lbl.status'),
            
            'socialLogin_' => Lang::t('user.profile.lbl.social.facebook.login'),
            'socialPost_' => Lang::t('user.profile.lbl.social.facebook.post'),
        );
    }


    public function scopes() {
        $t = $this->getTableAlias(false);
        return array(
            'active' => array(
                'condition' => $t . '.status_code=:activeStatus'.$t,
                'params' => array(
                    ':activeStatus'.$t => Option::STATUS_ACTIVE,
                ),
            ),
            'isAdmin'=>array(
                'condition'=>$t.'.user_role in ('.implode(',',  array_keys(Option::adminRole())).')',
            ),
            'isMerchant'=>array(
                'condition'=>$t.'.user_role in ('.implode(',',  array_keys(Option::merchantRole())).')',
            ),
            'isMember'=>array(
                'condition'=>$t.'.user_role in ('.implode(',',  array_keys(Option::memberRole())).')',
            ),
            'accessible'=>array(
                'condition' => $t.'.status_code <> :deletedStatus'.$t,
                'params' => array(
                    ':deletedStatus'.$t => Option::STATUS_DELETED,
                ),
            ),
        );
    }

    public function account($id = null) {
        $t = $this->getTableAlias(false);
        $this->getDbCriteria()->mergeWith(array(
            'condition' => $t.'.account_id=:accountId'.$t,
            'params' => array(
                ':accountId'.$t=>$id,
            ),
        ));
        return $this;
    }    
    
    public function withEmail($email){
        $t = $this->getTableAlias(false);
        $this->getDbCriteria()->mergeWith(array(
            'condition' => $t.'.email=:email'.$t,
            'params' => array(
                ':email'.$t=>$email,
            ),
        ));
        return $this;
    }
    
    public function authUsername($username = null) {
        $t = $this->getTableAlias(false);
        $this->getDbCriteria()->mergeWith(array(
            'condition' => implode(' OR ', array(
                $t.'.username=:username'.$t,
                $t.'.email=:email'.$t,
            )),
            'params' => array(
                ':username'.$t =>$username,
                ':email'.$t=>$username,
            ),
        ));
        return $this;
    }
    
    public function authPassword($password = null) {
        $t = $this->getTableAlias(false);
        $this->getDbCriteria()->mergeWith(array(
            'condition' => $t . '.password=:password'.$t,
            'params' => array(
                ':password'.$t =>$this->encryptPassword($password),
            ),
        ));
        return $this;
    }
    
    public function authSocial($params=array()){
        $provider=isset($params['provider'])? $params['provider']:'';
        $identifier=isset($params['identifier'])? $params['identifier']:'';
        
        $value1=trim(CJSON::encode(array($provider)),'[],');
        $value2=trim(CJSON::encode(array($provider=>$identifier)),'[],');
        
        $t = $this->getTableAlias(false);
        $criteria = new CDbCriteria;
        $criteria->compare($t.'.social_provider',$value1, true);
        $criteria->compare($t.'.social_identifier',$value2, true);

        $this->getDbCriteria()->mergeWith($criteria);
        return $this;
    }
       
    public function autoFill(){
        switch($this->scenario){
            case 'webmasterRegister':
            case 'adminRegister':
            case 'userRegister':
                $this->userRole_ = $this->selectiveValue($this->scenario, array(
                    'webmasterRegister'=>Option::USER_ROLE_WEBMASTER,
                    'adminRegister'=>Option::USER_ROLE_MEMBER,
                    'userRegister'=>Option::USER_ROLE_MEMBER,
                ));                
                $this->status_ = $this->selectiveValue($this->scenario, array(
                    'webmasterRegister'=>Option::STATUS_ACTIVE,
                    'adminRegister'=>Option::STATUS_ACTIVE,
                    'userRegister'=>Option::STATUS_ACITVE,
                ));
                
                $this->maritalStatus_ = Option::MARITAL_STATUS_SINGLE;
                $this->language_ = Option::LANGUAGE_ENGLISH;
                $this->gender_ = Option::GENDER_MALE;
                $this->country_ = Yii::app()->controller->countryCode;
                break;
            
            case 'update':
            case 'adminUpdate':
            case 'userUpdate':
                $this->firstName_ = $this->first_name;
                $this->lastName_ = $this->last_name;

                $this->gender_ = empty($this->gender_code)? Option::GENDER_MALE : $this->gender_code;
                $this->dob_ = $this->defaultBirthDate;
                $this->ethnic_ = $this->ethnic_code;
                $this->maritalStatus_ = $this->marital_status_code;
                
                $this->image_ = !empty($this->photo);

                $this->phoneNumber_ = $this->contact_number;
                $this->faxNumber_ = $this->fax_number;
                $this->mobileNumber_ = $this->mobile_number;
                $this->email_ = $this->email;
                
                $this->accountId_=(int)$this->account_id;
                $this->userRole_ = empty($this->user_role) ? Option::USER_ROLE_MEMBER : (int) $this->user_role;
                $this->language_ = $this->language_code;
                $this->username_ = $this->username;
                
                $this->status_= (int)$this->status_code;
                break;
                
            case 'userUpdateSetting':
                $this->language_ = $this->language_;
                //$this->privacy_ = $this->privacy;
                //$this->newsletter_ = $this->newsletter;
                //$this->notification_ = $this->notification;
                $this->socialLogin_ = $this->social_login;
                $this->socialPost_ = $this->social_post;
                break;
        }
    }
    
    /**
     * Retrieves a list of models based on the current search/filter conditions.
     * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
     */
    public function search($role='user') {
        // Warning: Please modify the following code to remove attributes that
        // should not be searched.
        $t = $this->getTableAlias(false);
        $criteria = new CDbCriteria;

        $criteria->compare($t . '.id', $this->id_, true);
        $criteria->compare($t . '.user_role', $this->userRole_);
        $criteria->compare($t . '.account_id', $this->accountId_);
        $criteria->compare('LOWER(' . $t . '.username)', strtolower($this->username_), true);

        $criteria->addSearchCondition('LOWER(' . $t . '.first_name)', strtolower($this->name_), true, 'OR');
        $criteria->addSearchCondition('LOWER(' . $t . '.last_name)', strtolower($this->name_), true, 'OR');

        $criteria->compare($t . '.gender_code', $this->gender_);
        $criteria->compare($t . '.marital_status_code', $this->maritalStatus_);
        $criteria->compare($t . '.ethnic_code', $this->ethnic_);

        $criteria->compare($t . '.contact_number', $this->phoneNumber_, true);
        $criteria->compare($t . '.fax_number', $this->faxNumber_, true);
        $criteria->compare($t . '.mobile_number', $this->mobileNumber_, true);
        $criteria->compare($t . '.email', $this->email_, true);

        $criteria->compare($t . '.status_code', $this->status_);
        
        if($role){
            //$role=$role=='user'? array_keys($this->memberRoleOption):array_keys($this->adminRoleOption);
            if($role=='user')
                $criteria->addNotInCondition($t.'.user_role', array_keys($this->adminRoleOption));
            elseif($role=='admin')
                $criteria->addInCondition($t.'.user_role', array_keys($this->adminRoleOption));
        }

        $sort = new CSort;
        $sort->sortVar = 'sort_';
        $sort->multiSort = true;
        $sort->defaultOrder = implode(', ', array(
            'LOWER(' . $t . '.first_name) ASC',
            'LOWER(' . $t . '.last_name) ASC',
            $t.'.id DESC',
        ));

        $sort->attributes = array(
            'name_'=>array(
                'asc'=>'LOWER('.$t.'.first_name) ASC, LOWER('.$t.'.last_name) ASC',
                'desc'=>'LOWER('.$t.'.first_name) DESC, LOWER('.$t.'.last_name) DESC',
            ),
            'firstName_' => array(
                'asc' => 'LOWER(' . $t . '.first_name) ASC',
                'desc' => 'LOWER(' . $t . '.first_name) DESC',
            ),
            'lastName_' => array(
                'asc' => 'LOWER(' . $t . '.last_name) ASC',
                'desc' => 'LOWER(' . $t . '.last_name) DESC',
            ),
            'gender_' => array(
                'asc' => $t . '.gender_code ASC',
                'desc' => $t . '.gender_code DESC',
            ),
            'userRole_' => array(
                'asc' => $t . '.user_role ASC',
                'desc' => $t . '.user_role DESC',
            ),
            'email_' => array(
                'asc' => 'LOWER(' . $t . '.email) ASC',
                'desc' => 'LOWER(' . $t . '.email) DESC',
            ),
            'status_'=>array(
                'asc'=>$t.'.status_code ASC',
                'desc'=>$t.'.status_code DESC',
            ),
        );

        return new ActiveDataProvider($this->accessible(), array(
            'criteria' => $criteria,
            'sort' => $sort,
            'pagination' => array(
                'pageSize' => Yii::app()->request->getParam('pageSize_', $this->pageSize_),
                'pageVar' => 'page_',
            ),
        ));
    }

    
    
    public function validateOldPassword($attribute, $params) {
        /*
        if ($this->encryptPassword($this->$attribute) !== $this->password) {
            $this->addError($attribute, Lang::t('password.lbl.wrong.old.password'));
        }*/
        if(empty($this->$attribute)) return ;        
        //if($this->password !== crypt($this->$attribute, $this->password)){
        if (!$this->isPasswordMatch($this->$attribute)) {
            $this->addError($attribute, Lang::t('user.password.lbl.wrong.old.password'));
        }
    }

    
    public function defaultUsername(){
        if (empty($this->username_) && !empty($this->email_)) {
            list($this->username_, ) = explode('@', $this->email_);
        }
        return $this->username_;
    }
    
    public function processUsername($username) {
        if(in_array($this->scenario, array('userUpdate', 'adminUpdate', 'socialUpdate')) && $this->username==$this->username_) return $username;
        $model=$this->accessible()->findAll('LOWER(username) LIKE :username',array(':username'=>strtolower($username).'%'));
        
        if(empty($model)) return $username;

        $index = count($model)+1;
        return implode('.',array(
            $username,
            $index,
        ));
    }

    public static function blowfishSalt($cost = 13) {
        if (!is_numeric($cost) || $cost < 4 || $cost > 31) {
            throw new Exception("cost parameter must be between 4 and 31");
        }
        $rand = array();
        for ($i = 0; $i < 8; $i += 1) {
            $rand[] = pack('S', mt_rand(0, 0xffff));
        }
        $rand[] = substr(microtime(), 2, 6);
        $rand = sha1(implode('', $rand), true);
        $salt = '$2a$' . sprintf('%02d', $cost) . '$';
        $salt .= strtr(substr(base64_encode($rand), 0, 22), array('+' => '.'));
        return $salt;
    }
    
    public function isPasswordMatch($password){
        return $this->password === crypt($password, $this->password);
    }
    
    public function encryptPassword($password) {
        //return md5($password);
        return crypt($password, self::blowfishSalt());
    }

    public function generatePassword() {
        if (Yii::app()->params['randomPasswordMode']) {
            $this->temporaryPassword = substr(md5(time()), 0, 8);
        } else {
            $this->temporaryPassword = Yii::app()->params['defaultPassword'];
        }
        return $this->encryptPassword($this->temporaryPassword);
    }
    
    public function generateVerificationCode(){
        $hash=implode('-',array(
            md5(Yii::app()->params['verificationCodeSalt']),
            md5($this->email_),
            time(),
        ));
        return substr(md5($hash), 0, 8).'-'.substr($hash, 0, 12);
    }

    public function findByActivationKey($key) {
        $criteria = new CDbCriteria;
        //$criteria->scopes = array('active');
        //$criteria->compare('status', 0);

        return $this->findByAttributes(array(
                    'status_code' => Option::STATUS_NEW,
                    'verification_code' => $key,
                        ), $criteria);
    }
    
    public function findByValidationCode($key) {
        $criteria = new CDbCriteria;
        //$criteria->scopes = array('active');
        //$criteria->compare('status', 0);
        return $this->findByAttributes(array(
                    'status_code' => Option::STATUS_ACTIVE,
                    'verification_code' => $key,
                        ), $criteria);
    }
    
    
    public function findBySocial($provider, &$socialUser){
        
        $value1=trim(CJSON::encode(array($provider)),'[],');
        $value2=trim(CJSON::encode(array($provider=>$socialUser->identifier)),'[],');
        
        $criteria = new CDbCriteria;
        $criteria->compare('social_provider',$value1, true);
        $criteria->compare('social_identifier',$value2, true);
        $criteria->compare('email', $socialUser->email);
        
        $criteria->addCondition(array(
            'status_code <> '.Option::STATUS_DELETED,
        ));
        return $this->find($criteria);
    }
    
    protected function beforeValidate(){        
        if(in_array($this->scenario, array('userRegister', 'userUpdate', 'adminRegister', 'adminUpdate', 'socialUpdate'))){
            $this->username_=$this->defaultUsername();
            $this->username_=$this->processUsername($this->username_);
        }
        return parent::beforeValidate();
    }
    
    protected function beforeSave() {
        if (parent::beforeSave()) {
           
            if(in_array($this->scenario, array('webmasterRegister', 'adminRegister', 'adminUpdate'))){
                $account=empty($this->accountId_)? null:Account::model()->accessible()->findByPk((int)$this->accountId_);                
                if(empty($this->account_id) && empty($this->accountId_)){
                    $this->user_role=$this->userRole_;
                }else{
                    $this->user_role = empty($account)? Option::USER_ROLE_MEMBER: $account->typeCode;
                }
                $this->account_id=$this->accountId_;
                $this->status_code = $this->status_;
            }
            
            if(in_array($this->scenario, array('userRegister'))){
                $this->user_role=$this->userRole_;
                $this->status_code=$this->status_;
                $this->verification_code = $this->generateVerificationCode();
                $this->last_login_time = $this->currentTime; // This field will be used to determine the verification code expiry
            }

            if(in_array($this->scenario, array('socialRegister'))){
                $this->user_role=$this->userRole_=Option::USER_ROLE_MEMBER;
                $this->status_code=$this->status_=Option::STATUS_ACTIVE;
                $this->language_=$this->defaultLanguage;
                $this->social_provider=CJSON::encode(array($this->socialProvider_));
                $this->social_identifier=CJSON::encode(array($this->socialProvider_=>$this->socialIdentifier_));
                $this->social_avatar_url=CJSON::encode(array($this->socialProvider_=>$this->socialAvatarUrl_));
                $this->social_profile_url=CJSON::encode(array($this->socialProvider_=>$this->socialProfileUrl_));
            }
                        
            if(in_array($this->scenario, array('socialUpdate'))){
                //$this->social_provider=$this->socialProvider_;
                
                $value=CJSON::decode($this->social_provider);
                $value[]=$this->socialProvider_;
                $this->social_provider=CJSON::encode(array_unique($value));
                
                $value=CJSON::decode($this->social_identifier);
                $value[$this->socialProvider_]=$this->socialIdentifier_;
                $this->social_identifier=CJSON::encode($value);
                
                $value=CJSON::decode($this->social_avatar_url);
                $value[$this->socialProvider_]=$this->socialAvatarUrl_;
                $this->social_avatar_url=CJSON::encode($value);
                
                $value=CJSON::decode($this->social_profile_url);
                $value[$this->socialProvider_]=$this->socialProfileUrl_;
                $this->social_profile_url=CJSON::encode($value);
            }
            
            if(in_array($this->scenario, array('socialRegister', 'webmasterRegister', 'adminRegister', 'adminUpdate', 'userRegister', 'userUpdate'))){
                $this->first_name = $this->firstName_;
                $this->last_name = $this->lastName_;
                $this->language_code = $this->language_;
                $this->gender_code = $this->gender_;
                $this->dob = empty($this->dob_)? null:date('Y-m-d', strtotime($this->dob_));
                $this->ethnic_code = $this->ethnic_;
                
                $this->email = $this->email_;
                $this->religion_code = $this->religion_;
                $this->marital_status_code = $this->maritalStatus_;
                $this->country_code = $this->country_;

                $this->contact_number= $this->phoneNumber_;
                $this->fax_number = $this->faxNumber_;
                $this->mobile_number = $this->mobileNumber_;

                $this->username = $this->username_;
            }//end if
            
            if (in_array($this->scenario, array('webmasterRegister', 'userRegister', 'adminRegister'))) {
                switch ($this->scenario) {
                    case 'webmasterRegister':
                    case 'userRegister':
                        $this->password = $this->encryptPassword($this->password_);
                        break;
                    case 'adminRegister':
                        $this->password = $this->generatePassword();
                        break;
                }//end switch
                $this->source=$this->source_;
                $this->source_info=$this->sourceInfo_;
            }

            if ($this->isNewRecord) {
            	$this->setCreateDateTime();
            	
                if($this->scenario=='userRegister') $this->last_login_time=$this->create_time;
            } else {
                $this->setUpdateDateTime();
            }
            return true;
        }
        else
            return false;
    }
   
    /**
     * User activation
     * @return type
     */
    public function getResetActivationCodeUrl(){
        return Yii::app()->createAbsoluteUrl('user/auth/resetactivation',array('k_'=>$this->verification_code));
    }
    
    public function getActivationUrl(){
        return Yii::app()->createAbsoluteUrl('user/auth/activate', array('k_'=>$this->verification_code));
    }
    
    public function getIsVerificationCodeExpired($day=null){
        $expiryLength = empty($day)? Yii::app()->params['verificationCodeExpiry'] . " day":$day.' day';
        return strtotime(date('Y-m-d H:i:s', strtotime($expiryLength, strtotime($this->last_login_time)))) < strtotime(date('Y-m-d H:i:s'));
    }
    
    public function resetActivationCode(){   
        $this->verification_code = $this->generateVerificationCode();
        $this->last_login_time = $this->currentTime; // This field will be used to determine the verification code expiry

        $this->beginTransaction();
        try{
            if ($this->save(false)) {
                $this->dataLog[get_class($this)]=$this->attributes;
            }
            
            if($this->hasErrors()){
                $this->rollback();
                return false;
            }else{
                $this->commit();
                $this->saveLog();
                return true;
            }
        } catch (Exception $e){
            $this->rollback();
        }
    }   
    
    public function activateRecord() {
        $this->status_code = Option::STATUS_ACTIVE;
        $this->beginTransaction();
        try{
            if ($this->save(false)) {
                $this->dataLog[get_class($this)]=$this->attributes;
            }  
            if($this->hasErrors()){
                $this->rollback();
                return false;
            }else{
                $this->commit();
                $this->saveLog();
                return true;
            }
        } catch (Exception $e){
            $this->rollback();
        }
    }
    
    public function updateAllRoleByAccount($accountId, $roleCode){
        return $this->updateAll(array('user_role'=>$roleCode), 'account_id=:accountId', array(':accountId'=>$accountId));
    }
    
    public function updateByAccountStatus($accountId, $statusCode){
        
        if ($statusCode == Option::STATUS_ACTIVE) {
            return $this->updateAll(array(
                        'status_code' => $statusCode,
                            ), implode(' AND ', array(
                        'account_id = :accountId',
                        'status_code = :accountStatus',
                            )), array(
                        ':accountId' => $accountId,
                        ':accountStatus' => Option::STATUS_AS_ACCOUNT,
            ));
        } else {
            return $this->updateAll(array(
                        'status_code' => Option::STATUS_AS_ACCOUNT,
                            ), implode(' AND ', array(
                        'account_id = :accountId',
                        'status_code = :activeStatus',
                        'status_code <> :deletedStatus',
                            )), array(
                        ':accountId' => $accountId,
                        ':activeStatus' => Option::STATUS_ACTIVE,
                        ':deletedStatus' => Option::STATUS_DELETED,
            ));
        }
    }
    
    public function updatePassword() {
        $this->password = $this->encryptPassword($this->password_);
        $this->dataLog[get_class($this)]=$this->attributes;
        if($this->save(true)){
            $this->saveLog();
            return true;
        }else
            return false;
    }

    public function updateLoginTime(){
        return $this->saveAttributes(array(
            'last_login_time'=>$this->currentTime,
        ));
    }
    
    public function disconnectSocial($provider=null){
        $this->scenario='socialDisconnect';
        $this->social_provider=null;
        $this->password=null;
        return $this->updateRecord();
    }
    
    public function updateViewCounter(){
        if(!Yii::app()->user->isGuest && Yii::app()->user->id == $this->id) return false;
        
        $this->beginTransaction();
        try{
            if($this->updateCounters(array('total_view'=>1), 'id=:id', array(':id'=>$this->id))){
                $this->saveViewLog();
            }
            if($this->hasErrors()){
                $this->rollback();
                return false;
            }else{
                $this->commit();
                return true;
            }
        }catch(Exception $e){
            $this->rollback();
            return false;
        }
    }
    
    public function getIsPasswordRequired(){
        return empty($this->password) && !$this->isSocialLogin;
    }
    
    public function resetPassword() {
        return $this->saveAttributes(array(
            'password'=>$this->generatePassword(),
        ));
    }

    /**
     * Password recovery
     */
    private $_setNewPasswordUrl;
    public function getSetNewPasswordUrl(){
        if(!empty($this->_setNewPasswordUrl)) return $this->_setNewPasswordUrl;
        $k=$this->generateVerificationCode();
        if($this->saveAttributes(array(
            'verification_code'=>$k,
            'update_time'=>$this->currentTime,
        ))){
            return $this->_setNewPasswordUrl=Yii::app()->createAbsoluteUrl('user/auth/setnewpassword',array(
                'a'=>'new',
                'k'=>$k,
            ));
        }else
            return ;
    }
    
    public function getIsResetPasswordCodeExpired($day=1){
        $expiryLength = empty($day)? Yii::app()->params['verificationCodeExpiry'] . " day":$day.' day';
        return strtotime(date('Y-m-d H:i:s', strtotime($expiryLength, strtotime($this->update_time)))) < strtotime(date('Y-m-d H:i:s'));
    }
    
    public function getUserRoleOption($id = null) {
        return Option::userRole($id);
    }

    public function getAdminRoleOption($id = null) {
        return Option::adminRole($id);
    }

    public function getMemberRoleOption($id = null) {
        //return Option::memberRole($id);
    	$option = array_intersect_key(Option::memberRole(), array(
    			Option::USER_ROLE_MEMBER => '',
    	));
    	if($id===null) return $option; return isset($option[$id])? $option[$id]:null;
    }

    public function getMerchantRoleOption($id = null) {
        return Option::merchantRole($id);
    }
    
    public function getGenderOption($id = null) {
        return Option::gender($id);
    }

    public function getAccountOption($id=null){
        $option=Account::model()->findAllNameInArray();
        if($id===null) return $option; return isset($option[$id])? $option[$id]:null;
    }
    
    public function getStatusOption($id = null) {
        $option=Option::recordStatus();
        unset(
            $option[Option::STATUS_DELETED],
            $option[Option::STATUS_UPDATED]
        );
        if($id===null) return $option; return isset($option[$id])? $option[$id]:null;
    }

    public function getLanguageOption($id = null) {
        return Option::language($id);
    }

    public function getEthnicOption($id = null) {
        return Option::ethnic($id);
    }

    public function getMaritalStatusOption($id = null) {
        return Option::maritalStatus($id);
    }

    public function getReligionOption($id = null) {
        return Option::religion($id);
    }

    public function getDefaultAvatar(){
        if($this->isSocialUser){
            if(!empty($this->socialAvatar)) return $this->socialAvatar;;
        }

        if(is_array($this->defaultImage)){
            return isset($this->defaultImage[$this->genderCode])? $this->defaultImage[$this->genderCode]: null;
        }else{ 
            return $this->defaultImage;
        }
    }

    public function getSquareAvatar(){
        return empty($this->photo)? $this->getDefaultAvatar(): CHtml::encode($this->photo->squareThumbnail);
    }
    
    public function getLargeSquareAvatar(){
        return empty($this->photo)? $this->getDefaultAvatar(): CHtml::encode($this->photo->largeSquareThumbnail);
    }
    
    public function getAvatar() {
        return empty($this->photo)? $this->getDefaultAvatar(): CHtml::encode($this->photo->thumbnail);
    }
    
    public function getSmallAvatar() {
        return empty($this->photo)? $this->getDefaultAvatar(): CHtml::encode($this->photo->smallThumbnail);
    }
    
    public function getMediumAvatar(){
        return empty($this->photo)? $this->getDefaultAvatar(): CHtml::encode($this->photo->mediumThumbnail);
    }
    
    public function getOriginalAvatar(){
        return empty($this->photo)? $this->getDefaultAvatar(): CHtml::encode($this->photo->originalFile);
    }
    
    public function getName() {
        return CHtml::encode(implode(' ', array_filter(array($this->first_name, $this->last_name))));
    }

    public function getFullName() {
        return CHtml::encode(implode(' ', array_filter(array(
                    $this->first_name,
                    $this->last_name,
        ))));
    }

    public function getFirstName() {
        return empty($this->first_name) ? '-' : CHtml::encode($this->first_name);
    }

    public function getLastName() {
        return empty($this->last_name) ? '-' : CHtml::encode($this->last_name);
    }

    public function getDisplayName() {
        return empty($this->username) ? '-' : CHtml::encode($this->username);
    }

    public function getHasAccount(){
        return !empty($this->account_id) && !empty($this->account);
    }
    
    public function getAccountId(){
        return (int)$this->account_id;
    }
    
    public function getRoleCode() {
        return (int) $this->user_role;
    }

    public function getRole() {
        return empty($this->user_role) ? '-' : CHtml::encode($this->getUserRoleOption((int) $this->user_role));
    }

    public function getContactNumber() {
        return empty($this->contact_number) ? $this->mobileNumber : $this->phoneNumber;
    }

    public function getPhoneNumber() {
        return $this->contact_number;
    }

    public function getFaxNumber() {
        return $this->fax_number;
    }

    public function getMobileNumber() {
       return $this->mobile_number;
    }

    public function getContactEmail() {
        return $this->email;
    }

    public function getGenderCode() {
        return CHtml::encode(strtolower($this->gender_code));
    }

    public function getGender() {
        //return empty($this->gender_code) ? '-' : CHtml::encode(Option::gender($this->gender_code));
        return empty($this->gender_code) ? '-' : CHtml::encode($this->getGenderOption($this->gender_code));
    }

    public function getEthnicCode() {
        return empty($this->ethnic_code) ? 0 : (int) $this->ethnic_code;
    }

    public function getEthnic() {
        return empty($this->ethnic_code) ? '-' : $this->getEthnicOption((int) $this->ethnic_code);
    }

    public function getReligionCode() {
        return empty($this->religion_code) ? 0 : (int) $this->religion_code;
    }

    public function getReligion() {
        return empty($this->religion_code) ? '-' : $this->getReligionOption((int) $this->religion_code);
    }

    public function getMaritalStatus() {
        return empty($this->marital_status_code) ? '-' : $this->getMaritalStatusOption((int) $this->marital_status_code);
    }

    public function getDefaultBirthDate() {
        return CHtml::encode(date(Yii::app()->params['dateFormat'], strtotime($this->dob)));
    }

    public function getBirthDate() {
        return empty($this->dob)? '' : CHtml::encode(date(Yii::app()->params['dateFormat'], strtotime($this->dob)));
    }

    public function getPreferredLanguageCode(){
        return empty($this->language_code) ? Yii::app()->params['defaultLanguage'] : $this->language_code;
    }
    
    public function getPreferredLanguage() {
        return $this->getLanguageOption($this->language_code);
    }

    public function getIsSocialUser(){
        return !empty($this->social_provider) && !empty($this->social_identifier);
    }
    
    public function getIsSocialLogin($provider=null){
        if($provider === null){
            return !empty($this->social_provider);
        }else{
            return empty($this->social_provider)? false: in_array($provider, CJSON::decode($this->social_provider));
        }
    }
        
    public function getSocialProvider(){
        $temp = CJSON::decode($this->social_provider);
        return empty($temp)? null: implode(',', $temp);
    }
    
    public function getSocialIdentifier(){
        $value = CJSON::decode($this->social_identifier);
        return isset($value[$this->socialProvider])? $value[$this->socialProvider]:null;
    }
    
    public function getSocialAvatar(){
        $value = CJSON::decode($this->social_avatar_url);
        return isset($value[$this->socialProvider])? $value[$this->socialProvider]:null;
    }
    
    public function getSocialProfileUrl(){
        $value = CJSON::decode($this->social_profile_url);
        return isset($value[$this->socialProvider])? $value[$this->socialProvider]:null;
    }
    
    public function getIsAdmin(){
        return in_array($this->user_role, array_keys($this->adminRoleOption));
    }
    
    public function getIsMerchant(){
        return in_array($this->user_role,array_keys($this->merchantRoleOption));
    }
    
    public function getIsMember(){
        return in_array($this->user_role,array_keys($this->memberRoleOption));
    }
    
    public function getIsEditMode(){
        return true;
    }
    
    public function getReturnUrl(){
        switch($this->user_role){
            case $this->isMerchant:
                //return isset(Yii::app()->params['merchantReturnUrl']) ? Yii::app()->params['merchantReturnUrl'] : null;
                return Yii::app()->createUrl('account/profile');
                break;
            case $this->isMember:
            case $this->isAdmin:
            default:
                //return isset(Yii::app()->params['userReturnUrl']) ? Yii::app()->params['userReturnUrl'] : null;
                //return Yii::app()->createUrl('user');
                return Yii::app()->homeUrl;
                break;
        }
    }
    
    public function getUrl(){
        switch($this->scenario){
            case 'update':
            default:
                //return 'javascript:void(0);';
                return Yii::app()->createAbsoluteUrl('user/public/index', array(
                    'id'=>$this->id, 
                    'title'=>$this->urlFormat($this->displayName),
                    ));
                break;
        }
    }    
    
    public function getLoginUrl(){
        return Yii::app()->createAbsoluteUrl('user/auth/login');
    }
    
    public function getUnsubscribeEDMUrl(){
        return Yii::app()->createAbsoluteUrl('edm/user/unsubscribe',array(
            'email'=>rawurlencode($this->email),
        ));
    }
    
    public function getConnectFacebookUrl(){
        return Yii::app()->createAbsoluteUrl('user/hybridauth/connect', array('provider'=>'Facebook'));
    }
    
    public function getDisconnectFacebookUrl(){
        return Yii::app()->createAbsoluteUrl('user/profile/disconnectsociallogin', array('provider'=>'Facebook'));
    }
    
    public function generateCookies(){
        Yii::app()->request->cookies['userLoginId'] = new CHttpCookie('userLoginId', $this->id);
    }
    
    
}//end class